package com.ruoyi.web.controller.tool.designpattern.structuralPatterns.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * 组合模式
 *
 * @author Hack2003
 * @date 2024/3/21 16:30
 **/
// 1. 抽象组件接口，定义所有对象共有的行为
interface Component {
    void add(Component component);

    void remove(Component component);

    Component getChild(int index);

    String getName();

    void printAll(); // 打印自身及子组件的信息
}

// 2. 叶节点（具体组件类）
class Leaf implements Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException("叶子节点不支持添加子组件");
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException("叶子节点不支持移除子组件");
    }

    @Override
    public Component getChild(int index) {
        throw new UnsupportedOperationException("叶子节点没有子组件");
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void printAll() {
        System.out.println("叶节点: " + getName());
    }
}

// 3. 容器节点（容器组件类）
class Composite implements Component {
    private List<Component> children = new ArrayList<>();
    private String name;

    public Composite(String name) {
        this.name = name;
    }

    @Override
    public void add(Component component) {
        children.add(component);
    }

    @Override
    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public Component getChild(int index) {
        return children.get(index);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void printAll() {
        System.out.println("容器节点: " + getName());

        for (Component child : children) {
            child.printAll();
        }
    }
}

/**
 * 它允许你将对象组合成树形结构来表现“整体-部分”的层次结构，
 * 并且用户可以以一致的方式处理单个对象和整个对象的集合。
 * 在Java中，这种模式常用于表示目录和文件系统、组织结构等场景
 */
public class Test {
    public static void main(String[] args) {
        // 创建一个根复合节点
        Composite root = new Composite("Root");

        // 添加子节点
        root.add(new Leaf("叶子节点 A"));
        root.add(new Composite("容器节点 B"));

        System.out.println("输出当前节点名称："+root.getChild(0).getName());
        System.out.println("输出当前节点名称："+root.getChild(1).getName());
        // 在内部复合节点上添加叶节点
        if(root.getChild(1) instanceof Composite) {
            System.out.println("准备往节点【"+root.getChild(1).getName()+"】添加子节点");
            ((Composite) root.getChild(1)).add(new Leaf("叶子节点 B1"));
            ((Composite) root.getChild(1)).add(new Leaf("叶子节点 B2"));
        }else{
            System.out.println("根节点属于叶子节点，它不包含子节点");
        }

        // 打印整个树状结构
        root.printAll();
    }
}
